//
//  ___PROJECTNAMEASIDENTIFIER___AppDelegate.m
//  ___PROJECTNAME___
//
//  Created by ___FULLUSERNAME___ on ___DATE___.
//  Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
//

#import "___PROJECTNAMEASIDENTIFIER___AppDelegate.h"
#import "___PROJECTNAMEASIDENTIFIER___ViewController.h"

#import "ChattyConfig.h"
#import "LocalRoom.h"
#import "RemoteRoom.h"

@implementation ___PROJECTNAMEASIDENTIFIER___AppDelegate

@synthesize window;
@synthesize viewController;
@synthesize webView;

// cache for image picker
@synthesize dataPath;

// chatty client and server objects
@synthesize chatRoom;
@synthesize serverBrowser;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    
	// initialize the cache
	[self initCache];
	[self clearCache];

	// add the webview
	webView = [ [ UIWebView alloc ] 
		initWithFrame:[ [ UIScreen mainScreen ] bounds ] ];
	[ viewController.view addSubview: webView ];

	// load content into the webview

	NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] 
		pathForResource:@"index" 
		ofType:@"html" 
		inDirectory:@"www"]];
	NSURLRequest *request = [NSURLRequest requestWithURL:url];
	webView.delegate = self;

	[webView loadRequest:request];


	// Override point for customization after app launch    
	[window addSubview:viewController.view];
	[window makeKeyAndVisible];
	
	return YES;
}


- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}

//webview delegate methods

- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {

	NSURL *url = [request URL];

	NSString *scheme = [[url scheme] lowercaseString];

	//NSLog(@"url: %@", url);
	//NSLog(@"scheme: %@", scheme);
	
	if ([url isFileURL]) {
		//NSLog(@"description: %@", [url description]);
		return YES;
	} else if ([scheme isEqualToString:@"http"]) {
		return YES;
	} else if ([scheme isEqualToString:@"hook"]) {
		 NSLog(@"unhook: %@", [url absoluteString]);
		 [self unHook: [url absoluteString]];
	}
	
	return NO;

}

- (void) unHook:(NSString*)hook {
	//NSLog(@"unhook: %@", hook);
	NSArray *components = [hook componentsSeparatedByString:@":"];
	if ([components count] < 2) { return; }

	NSString *command = [components objectAtIndex:1];
	if ([command isEqualToString:@"log"]) { if ([components count] > 2) {
			 NSLog(@"log: %@", [self unescapeString: (NSString*)[components objectAtIndex: 2]] );
		 return;
	} }


	//if ([components count] < 3) { return; }

	if ([command isEqualToString:@"alert"]) { if ([components count] > 4) {
		UIAlertView *a = [[UIAlertView alloc]
			initWithTitle:[(NSString*)[components objectAtIndex: 2] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]
			message:[(NSString*)[components objectAtIndex: 4] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]
			delegate:nil
			cancelButtonTitle:[(NSString*)[components objectAtIndex: 3] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]
			otherButtonTitles:nil
		];
		[a show];
		[a release];
	} return; }


	if ([command isEqualToString:@"device"]) { if ([components count] > 3) {
		if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"uuid"]) {

		[webView stringByEvaluatingJavaScriptFromString:
			[NSString stringWithFormat:
				@"key_callback(\"%@\",\"%@\");", 
				[components objectAtIndex: 3], 
				[components objectAtIndex: 3]]];
		[webView stringByEvaluatingJavaScriptFromString:
			[NSString stringWithFormat:
				@"do_callback(\"%@\", ['%@']);",
				[components objectAtIndex: 3],
				[[UIDevice currentDevice] uniqueIdentifier]]];
		}
		else if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"name"]) {

		[webView stringByEvaluatingJavaScriptFromString:
			[NSString stringWithFormat:
				@"key_callback(\"%@\",\"%@\");", 
				[components objectAtIndex: 3], 
				[components objectAtIndex: 3]]];
		[webView stringByEvaluatingJavaScriptFromString:
			[NSString stringWithFormat:
				@"do_callback(\"%@\", ['%@']);",
				[components objectAtIndex: 3],
				[[[UIDevice currentDevice] name]
				stringByAddingPercentEscapesUsingEncoding: 
				NSUTF8StringEncoding]
					]];
		}
	} }
	else if ([command isEqualToString:@"photo"]) { if ([components count] > 3) {
		NSLog(@"pick photo");
		UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
		[webView stringByEvaluatingJavaScriptFromString:
			[NSString stringWithFormat:
				@"key_callback(\"%@\",\"%@\");", 
				[components objectAtIndex: 3], 
				imagePicker] ];
		imagePicker.delegate = self;
		[viewController presentModalViewController:imagePicker animated:YES];
		[imagePicker release];
	} }


	else if ([command isEqualToString:@"music"]) { if ([components count] > 3) {
		if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"choose"]) {
			NSLog(@"pick music");
			MPMediaPickerController *picker =
				    [[MPMediaPickerController alloc]
					    initWithMediaTypes: MPMediaTypeAnyAudio];

			[webView stringByEvaluatingJavaScriptFromString:
				[NSString stringWithFormat:
					@"key_callback(\"%@\",\"%@\");", 
					[components objectAtIndex: 3], 
					picker] ];

			[picker setDelegate: self];
			[picker setAllowsPickingMultipleItems: YES];

			picker.prompt =
				    NSLocalizedString (@"Add songs to play",
									    "Prompt in media item picker");
			 
			[viewController presentModalViewController: picker animated: YES];
			[picker release];
			return;
		}

		[webView stringByEvaluatingJavaScriptFromString:
			[NSString stringWithFormat:
				@"key_callback(\"%@\",\"%@\");", 
				[components objectAtIndex: 3], 
				[components objectAtIndex: 3]]];


		if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"stop"]) {
			[[MPMusicPlayerController iPodMusicPlayer] stop];
		} else if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"play"]) {
			[[MPMusicPlayerController iPodMusicPlayer] play];
		} else if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"pause"]) {
			[[MPMusicPlayerController iPodMusicPlayer] pause];
		} else if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"prev"]) {
			[[MPMusicPlayerController iPodMusicPlayer] skipToPreviousItem];
		} else if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"next"]) {
			[[MPMusicPlayerController iPodMusicPlayer] skipToNextItem];
		}

		[webView stringByEvaluatingJavaScriptFromString:
			[NSString stringWithFormat:
				@"do_callback(\"%@\");",
				[components objectAtIndex: 3]]];
	} }

	// Chatty methods
	else if([command isEqualToString:@"server"]) { if ([components count] > 3) {
		
		NSLog(@"server: %@", [components objectAtIndex:2]); 
		[ChattyConfig getInstance].name = [components objectAtIndex:2];
		[ChattyConfig getInstance].service = [components objectAtIndex:3];
		if ( chatRoom != nil ) {
			[chatRoom stop];
			chatRoom = nil;
		}
		chatRoom = [[[LocalRoom alloc] init] autorelease];
		chatRoom.delegate = self;
		[chatRoom start];
		//NSLog(@"started server");
		[webView stringByEvaluatingJavaScriptFromString:@"started_chat_server()"];

	} } 
	else if([command isEqualToString:@"connect"]) { if ([components count] > 2) {
	    [self connectWithServer: 
		[(NSString*)[components objectAtIndex: 2] 
			stringByReplacingPercentEscapesUsingEncoding: 
				NSUTF8StringEncoding]];
	} }
	else if([command isEqualToString:@"client"]) { if ([components count] > 3) {
		
		NSLog(@"client: %@", [components objectAtIndex:2]); 
		[ChattyConfig getInstance].name = [components objectAtIndex:2];
		[ChattyConfig getInstance].service = [components objectAtIndex:3];
		if ( serverBrowser != nil ) {
			[serverBrowser stop];
			serverBrowser = nil;
		}

		serverBrowser = [[ServerBrowser alloc] init];
		serverBrowser.delegate = self;
		[serverBrowser start];

	} }
	else if([command isEqualToString:@"send"]) { if ([components count] > 2) {
		
		NSLog(@"send: %@", [components objectAtIndex:2]); 
		[chatRoom broadcastChatMessage:[self unescapeString: [components objectAtIndex:2]] fromUser:[ChattyConfig getInstance].name];
	} }
}


- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
	// The user canceled -- simply dismiss the image picker.
	NSLog(@"cancel photo");
	[viewController dismissModalViewControllerAnimated:YES];
	[webView stringByEvaluatingJavaScriptFromString:
		[NSString stringWithFormat:
			@"do_callback(\"%@\");", picker] ];
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)selectedImage editingInfo:(NSDictionary *)editingInfo {
	NSLog(@"picked photo");

	[viewController dismissModalViewControllerAnimated:YES];
	NSString* png = [[self.dataPath stringByAppendingPathComponent:
		[self newUUID]] 
			stringByAppendingPathExtension:@"png" ];
	NSLog(@"%@", png);

	if([UIImagePNGRepresentation(selectedImage) writeToFile: png atomically:YES]) {
		NSLog(@"saved %@", png);

		[webView stringByEvaluatingJavaScriptFromString: 
			[[NSString alloc] initWithFormat:
			@"do_callback(\"%@\", [\"%@\"]);", picker, 
			[NSURL fileURLWithPath: png isDirectory:NO]]];
	} else {
		@"do_callback(\"%@\");", picker, 
		NSLog(@"failed to save %@", png);
	}
}

- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) collection {
     
	[viewController dismissModalViewControllerAnimated: YES];
	// use the ipod application to play the selected files
	
	MPMusicPlayerController *musicPlayer = [MPMusicPlayerController iPodMusicPlayer];
	[musicPlayer setQueueWithItemCollection: collection];
	[musicPlayer play];

	NSEnumerator *e = [[collection items] objectEnumerator];
	id object;
	NSString *s = @"'items'";
	while (object = [e nextObject]) {
		NSLog(@"item %@", [(MPMediaItem*) object valueForProperty: MPMediaItemPropertyPersistentID]);
		s = [NSString stringWithFormat: @"%@,'%@'", s,
			[(MPMediaItem*) object valueForProperty: 
				MPMediaItemPropertyPersistentID]];
	}
	NSLog(@"%@", s);

	[webView stringByEvaluatingJavaScriptFromString:
		[NSString stringWithFormat:
			@"do_callback(\"%@\", [%@]);", mediaPicker, s] ];
	//[self updatePlayerQueueWithMediaCollection: collection];
}

- (void) mediaPickerDidCancel: (MPMediaPickerController *) mediaPicker {
	[viewController dismissModalViewControllerAnimated: YES];
	[webView stringByEvaluatingJavaScriptFromString:
		[NSString stringWithFormat:
			@"do_callback(\"%@\");", mediaPicker] ];
}

- (void) initCache
{
	/* create path to cache directory inside the application's Documents directory */
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    self.dataPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"FileCache"];

	/* check for existence of cache directory */
	if ([[NSFileManager defaultManager] fileExistsAtPath:dataPath]) {
		return;
	}
		
	/* create a new cache directory */
	if (![[NSFileManager defaultManager] createDirectoryAtPath:dataPath 
								   withIntermediateDirectories:NO
													attributes:nil 
														 error:&error]) {
		NSLog(@"couldn't create cache directory!");
		NSLog(@"%@", error);
		return;
	}
}

	
/* removes every file in the cache directory */

- (void) clearCache
{
	/* remove the cache directory and its contents */
	if (![[NSFileManager defaultManager] removeItemAtPath:dataPath error:&error]) {
		NSLog(@"couldn't delete cache item!");
		NSLog(@"%@", error);
		return;
	}
	
	/* create a new cache directory */
	if (![[NSFileManager defaultManager] createDirectoryAtPath:dataPath 
								   withIntermediateDirectories:NO
													attributes:nil 
														 error:&error]) {
		NSLog(@"couldn't recreate cache directory!");
		NSLog(@"%@", error);
		return;
	}
	NSLog(@"cache ready at %@", dataPath);

	//[self initUI];
}	

- (NSString *)escapeString: (NSString*)s {
	return [s stringByAddingPercentEscapesUsingEncoding: 
			NSUTF8StringEncoding];
}

- (NSString *)unescapeString: (NSString*)s {
	return [s stringByReplacingPercentEscapesUsingEncoding: 
			NSUTF8StringEncoding];
}

- (NSString *)newUUID
{
    CFUUIDRef       uuid;
    CFStringRef     uuidStr;
    NSString *      result;
    
    uuid = CFUUIDCreate(NULL);
    assert(uuid != NULL);
    
    uuidStr = CFUUIDCreateString(NULL, uuid);
    assert(uuidStr != NULL);
    
    result = [NSString stringWithFormat:@"%@", uuidStr];
    
    CFRelease(uuidStr);
    CFRelease(uuid);
    
    return result;
}

// Chatty Delegate methods:

- (void)updateServerList {
	NSLog(@"found servers"); 

	NSEnumerator *e = [serverBrowser.servers objectEnumerator];
	id object;
	NSString *s = @"'servers'";
	while (object = [e nextObject]) {
		//NSLog(@"key %@", (NSNetService*) object);
		//NSLog(@"name %@", [(NSNetService*) object name]);
		
		NSNetService* server = (NSNetService*) object;
		s = [NSString stringWithFormat: @"%@, '%@'", s,
		    [[server name]
			stringByAddingPercentEscapesUsingEncoding: 
			NSUTF8StringEncoding]
		    ];
	}
	[webView stringByEvaluatingJavaScriptFromString:
	     [NSString stringWithFormat: @"found_servers([%@]);", s]];
	NSLog(@"%@", s);
}

- (void)connectWithServer:(NSString*)name {
	if ( chatRoom != nil ) {
		[chatRoom stop];
		chatRoom = nil;
	}
	NSLog(@"still good?");

	NSEnumerator *e = [serverBrowser.servers objectEnumerator];
	id object;

	NSNetService* ns = nil;
	while (object = [e nextObject]) {
		ns = (NSNetService*) object;
		NSLog(@"%@", ns);
		NSLog(@"name %@", [ns name]);
		if ([name isEqualToString: [ns name]]) {
			break;
		}
		ns = nil;
	}
	if (nil == ns) { return; }

	chatRoom = [[[RemoteRoom alloc] initWithNetService: ns] autorelease];
	chatRoom.delegate = self;
	[chatRoom start];
	[serverBrowser stop];
	NSLog(@"connected to server"); 
	[webView stringByEvaluatingJavaScriptFromString:@"connected()"];
	return;

}


- (void)displayChatMessage:(NSString*)message fromUser:(NSString*)userName {
	NSLog(@"message: %@: %@", userName, message); 
	NSString* jsString = [NSString stringWithFormat:@"received_message(['%@', '%@']);", [self escapeString: userName], [self escapeString: message]];
	[webView stringByEvaluatingJavaScriptFromString:jsString];
}

- (void)roomTerminated:(id)room reason:(NSString*)reason {
	NSLog(@"exit: %@", reason); 
	[webView stringByEvaluatingJavaScriptFromString:@"disconnected()"];
}

#pragma mark -
#pragma mark NSNetService Delegate Method Implementations

// Called if we weren't able to resolve net service
- (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict {
	// somehow indicate that this service is no longer available
}


// Called when net service has been successfully resolved
- (void)netServiceDidResolveAddress:(NSNetService *)sender {

  // Save connection info
	[webView stringByEvaluatingJavaScriptFromString:
		[NSString stringWithFormat: @"found_server({host: '%@', port: '%@', name: '%@'});",
		    sender.hostName,
		    sender.port,
		    [[sender name]
			stringByAddingPercentEscapesUsingEncoding: 
			NSUTF8StringEncoding]
		    ]
	];
  
}

@end
